package com.tiny.conf.client.listener;

import com.tiny.conf.client.spring.TinyConfFactory;
import com.tiny.conf.core.factory.TinyConfBaseFactory;
import com.tiny.conf.core.listener.TinyConfListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanRefreshTinyConfListener implements TinyConfListener {
    /**
     * 该函数onChange在接收到键值对更新时触发，功能为：
     * 根据键key从key2BeanField映射中获取关联的BeanField列表。
     * 若列表非空，则遍历列表中的每个BeanField对象。
     * 使用新值value刷新（或更新）每个BeanField对象。
     * 刷新操作由TinyConfFactory类的静态方法refreshBeanField执行。
     * @param key
     * @param value
     * @throws Exception
     */
    @Override
    public void onChange(String key, String value) throws Exception {
        List<BeanField> beanFieldList = key2BeanField.get(key);
        if (beanFieldList != null && beanFieldList.size() > 0) {
            for (BeanField beanField : beanFieldList) {
                TinyConfFactory.refreshBeanField(beanField,value,null);
            }
        }
    }

    // ---------------------- listener ----------------------

    // object + field
    public static class BeanField {
        // bean名
        private String beanName;
        // bean 属性
        private String property;

        public BeanField() {
        }

        public BeanField(String beanName, String property) {
            this.beanName = beanName;
            this.property = property;
        }

        public String getBeanName() {
            return beanName;
        }

        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }

        public String getProperty() {
            return property;
        }

        public void setProperty(String property) {
            this.property = property;
        }
    }

    // key : object-field[]
    private static Map<String, List<BeanField>> key2BeanField = new ConcurrentHashMap<String, List<BeanField>>();


    /**
     * 具体步骤如下：
     * 获取或初始化列表：
     *      通过键值 key 从 key2BeanField 字典中获取对应的 beanFieldList。
     *      如果 beanFieldList 为 null，则创建一个新的 ArrayList 并将其与 key 关联。
     * 检查重复：
     *      遍历 beanFieldList 中的每个 BeanField 对象。
     *      检查每个 BeanField 的 beanName 和 property 是否与传入的 beanField 相同。
     *      如果存在相同的 BeanField，则直接返回，避免重复添加。
     * 添加新对象：
     *      如果列表中没有相同的 BeanField，则将新的 beanField 添加到列表中。
     * 该函数的主要目的是：
     * 根据键值 key 管理 BeanField 对象的列表。
     * 确保每个键值对应的 BeanField 列表中不会存在重复的条目。
     * @param key
     * @param beanField
     */
    public static void addBeanField(String key, BeanField beanField) {
        // 1. 获取当前键值对应的BeanField列表
        List<BeanField> beanFieldList = key2BeanField.get(key);

        // 2. 如果列表不存在，则创建并初始化
        if (beanFieldList == null) {
            beanFieldList = new ArrayList<>();
            key2BeanField.put(key, beanFieldList);
        }

        // 3. 遍历列表，检查是否存在相同的BeanField
        for (BeanField item : beanFieldList) {
            if (item.getBeanName().equals(beanField.getBeanName())
                    && item.getProperty().equals(beanField.getProperty())) {
                return; // 如果存在相同的BeanField，则直接返回，避免重复添加
            }
        }

        // 4. 如果列表中没有相同的BeanField，则添加新的BeanField
        beanFieldList.add(beanField);
    }

}
